broadway: Rename gdkbroadway-server-client.c to gdkbroadway-server.c
authorAlexander Larsson <alexl@redhat.com>
Thu, 27 Dec 2012 20:10:44 +0000 (21:10 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 27 Dec 2012 21:56:04 +0000 (22:56 +0100)
gdk/broadway/Makefile.am
gdk/broadway/gdkbroadway-server-client.c [deleted file]
gdk/broadway/gdkbroadway-server.c [new file with mode: 0644]

index 35f5633099a575343e4a264a5c48643abe43e89e..a06224037040f205d35be3cdd8ae40ddefbd7e10 100644 (file)
@@ -73,7 +73,7 @@ libgdk_broadway_la_SOURCES =          \
        gdkwindow-broadway.h    \
        gdkprivate-broadway.h   \
        gdkbroadway-server.h    \
-       gdkbroadway-server-client.c
+       gdkbroadway-server.c
 
 broadwayd_SOURCES = \
        broadway-protocol.h             \
diff --git a/gdk/broadway/gdkbroadway-server-client.c b/gdk/broadway/gdkbroadway-server-client.c
deleted file mode 100644 (file)
index a2f9e00..0000000
+++ /dev/null
@@ -1,685 +0,0 @@
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "gdkbroadway-server.h"
-
-#include "gdkprivate-broadway.h"
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <gio/gunixsocketaddress.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-typedef struct BroadwayInput BroadwayInput;
-
-struct _GdkBroadwayServer {
-  GObject parent_instance;
-
-  guint32 next_serial;
-  GSocketConnection *connection;
-
-  guint32 recv_buffer_size;
-  guint8 recv_buffer[1024];
-
-  guint process_input_idle;
-  GList *incomming;
-  
-};
-
-struct _GdkBroadwayServerClass
-{
-  GObjectClass parent_class;
-};
-
-static gboolean input_available_cb (gpointer stream, gpointer user_data);
-
-G_DEFINE_TYPE (GdkBroadwayServer, gdk_broadway_server, G_TYPE_OBJECT)
-
-static void
-gdk_broadway_server_init (GdkBroadwayServer *server)
-{
-  server->next_serial = 1;
-}
-
-static void
-gdk_broadway_server_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (gdk_broadway_server_parent_class)->finalize (object);
-}
-
-static void
-gdk_broadway_server_class_init (GdkBroadwayServerClass * class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-
-  object_class->finalize = gdk_broadway_server_finalize;
-}
-
-gboolean
-_gdk_broadway_server_lookahead_event (GdkBroadwayServer  *server,
-                                     const char         *types)
-{
-
-  return FALSE;
-}
-
-gulong
-_gdk_broadway_server_get_next_serial (GdkBroadwayServer *server)
-{
-  return (gulong)server->next_serial;
-}
-
-GdkBroadwayServer *
-_gdk_broadway_server_new (int port, GError **error)
-{
-  GdkBroadwayServer *server;
-  char *basename;
-  GSocketClient *client;
-  GSocketConnection *connection;
-  GSocketAddress *address;
-  GPollableInputStream *pollable;
-  GInputStream *in;
-  GSource *source;
-  char *path;
-
-  basename = g_strdup_printf ("broadway%d.socket", port);
-  path = g_build_filename (g_get_user_runtime_dir (), basename, NULL);
-  g_free (basename);
-
-  address = g_unix_socket_address_new_with_type (path, -1,
-                                                G_UNIX_SOCKET_ADDRESS_ABSTRACT);
-  g_free (path);
-
-  client = g_socket_client_new ();
-
-  error = NULL;
-  connection = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (address), NULL, error);
-  
-  g_object_unref (address);
-  g_object_unref (client);
-
-  if (connection == NULL)
-    return NULL;
-
-  server = g_object_new (GDK_TYPE_BROADWAY_SERVER, NULL);
-  server->connection = connection;
-
-  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
-  pollable = G_POLLABLE_INPUT_STREAM (in);
-
-  source = g_pollable_input_stream_create_source (pollable, NULL);
-  g_source_attach (source, NULL);
-  g_source_set_callback (source, (GSourceFunc)input_available_cb, server, NULL);
-
-  return server;
-}
-
-guint32
-_gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server)
-{
-  return 0;
-}
-
-static guint32
-gdk_broadway_server_send_message_with_size (GdkBroadwayServer *server, BroadwayRequestBase *base,
-                                           gsize size, guint32 type)
-{
-  GOutputStream *out;
-  gsize written;
-
-  base->size = size;
-  base->type = type;
-  base->serial = server->next_serial++;
-
-  out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection));
-
-  if (!g_output_stream_write_all (out, base, size, &written, NULL, NULL))
-    {
-      g_printerr ("Unable to write to server\n");
-      exit (1);
-    }
-
-  g_assert (written == size);
-
-  return base->serial;
-}
-
-#define gdk_broadway_server_send_message(_server, _msg, _type) \
-  gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type)
-
-static void
-parse_all_input (GdkBroadwayServer *server)
-{
-  guint8 *p, *end;
-  guint32 size;
-  BroadwayReply *reply;
-
-  p = server->recv_buffer;
-  end = p + server->recv_buffer_size;
-
-  while (p + sizeof (guint32) <= end)
-    {
-      memcpy (&size, p, sizeof (guint32));
-      if (p + size > end)
-       break;
-
-      reply = g_memdup (p, size);
-      p += size;
-
-      server->incomming = g_list_append (server->incomming, reply);
-    }
-  
-  if (p < end)
-    memmove (server->recv_buffer, p, end - p);
-  server->recv_buffer_size = end - p;
-}
-
-static void
-read_some_input_blocking (GdkBroadwayServer *server)
-{
-  GInputStream *in;
-  gssize res;
-
-  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
-
-  g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
-  res = g_input_stream_read (in, &server->recv_buffer[server->recv_buffer_size],
-                            sizeof (server->recv_buffer) - server->recv_buffer_size,
-                            NULL, NULL);
-
-  if (res <= 0)
-    {
-      g_printerr ("Unable to read from broadway server\n");
-      exit (1);
-    }
-
-  server->recv_buffer_size += res;
-}
-
-static void
-read_some_input_nonblocking (GdkBroadwayServer *server)
-{
-  GInputStream *in;
-  GPollableInputStream *pollable;
-  gssize res;
-  GError *error;
-
-  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
-  pollable = G_POLLABLE_INPUT_STREAM (in);
-
-  g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
-  error = NULL;
-  res = g_pollable_input_stream_read_nonblocking (pollable, &server->recv_buffer[server->recv_buffer_size],
-                                                 sizeof (server->recv_buffer) - server->recv_buffer_size,
-                                                 NULL, &error);
-
-  if (res < 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
-    {
-      g_error_free (error);
-      res = 0;
-    }
-  else if (res <= 0)
-    {
-      g_printerr ("Unable to read from broadway server: %s\n", error ? error->message : "eof");
-      exit (1);
-    }
-
-  server->recv_buffer_size += res;
-}
-
-static BroadwayReply *
-find_response_by_serial (GdkBroadwayServer *server, guint32 serial)
-{
-  GList *l;
-
-  for (l = server->incomming; l != NULL; l = l->next)
-    {
-      BroadwayReply *reply = l->data;
-
-      if (reply->base.in_reply_to == serial)
-       return reply;
-    }
-
-  return NULL;
-}
-
-static void
-process_input_messages (GdkBroadwayServer *server)
-{
-  BroadwayReply *reply;
-
-  if (server->process_input_idle != 0)
-    {
-      g_source_remove (server->process_input_idle);
-      server->process_input_idle = 0;
-    }
-  
-  while (server->incomming)
-    {
-      reply = server->incomming->data;
-      server->incomming =
-       g_list_delete_link (server->incomming,
-                           server->incomming);
-
-      if (reply->base.type == BROADWAY_REPLY_EVENT)
-       _gdk_broadway_events_got_input (&reply->event.msg);
-      else
-       g_warning ("Unhandled reply type %d\n", reply->base.type);
-      g_free (reply);
-    }
-}
-
-static gboolean
-process_input_idle_cb (GdkBroadwayServer *server)
-{
-  server->process_input_idle = 0;
-  process_input_messages (server);
-  return G_SOURCE_REMOVE;
-}
-
-static void
-queue_process_input_at_idle (GdkBroadwayServer *server)
-{
-  if (server->process_input_idle == 0)
-    server->process_input_idle =
-      g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc)process_input_idle_cb, server, NULL);
-}
-
-static gboolean
-input_available_cb (gpointer stream, gpointer user_data)
-{
-  GdkBroadwayServer *server = user_data;
-
-  read_some_input_nonblocking (server);
-  parse_all_input (server);
-
-  process_input_messages (server);
-
-  return G_SOURCE_CONTINUE;
-}
-
-static BroadwayReply *
-gdk_broadway_server_wait_for_reply (GdkBroadwayServer *server,
-                                   guint32 serial)
-{ 
-  BroadwayReply *reply;
-  
-  while (TRUE)
-    {
-      reply = find_response_by_serial (server, serial);
-      if (reply)
-       {
-         server->incomming = g_list_remove (server->incomming, reply);
-         return reply;
-       }
-
-      read_some_input_blocking (server);
-      parse_all_input (server);
-    }
-
-  queue_process_input_at_idle (server);
-}
-
-void
-_gdk_broadway_server_flush (GdkBroadwayServer *server)
-{
-  BroadwayRequestFlush msg;
-
-  gdk_broadway_server_send_message(server, msg, BROADWAY_REQUEST_FLUSH);
-}
-
-void
-_gdk_broadway_server_sync (GdkBroadwayServer *server)
-{
-  BroadwayRequestSync msg;
-  guint32 serial;
-  BroadwayReply *reply;
-
-  serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_SYNC);
-  reply = gdk_broadway_server_wait_for_reply (server, serial);
-
-  g_assert (reply->base.type == BROADWAY_REPLY_SYNC);
-
-  g_free (reply);
-
-  return;
-}
-
-void
-_gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
-                                 guint32            *toplevel,
-                                 gint32             *root_x,
-                                 gint32             *root_y,
-                                 guint32            *mask)
-{
-  BroadwayRequestQueryMouse msg;
-  guint32 serial;
-  BroadwayReply *reply;
-
-  serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_QUERY_MOUSE);
-  reply = gdk_broadway_server_wait_for_reply (server, serial);
-
-  g_assert (reply->base.type == BROADWAY_REPLY_QUERY_MOUSE);
-
-  if (toplevel)
-    *toplevel = reply->query_mouse.toplevel;
-  if (root_x)
-    *root_x = reply->query_mouse.root_x;
-  if (root_y)
-    *root_y = reply->query_mouse.root_y;
-  if (mask)
-    *mask = reply->query_mouse.mask;
-  
-  g_free (reply);
-}
-
-guint32
-_gdk_broadway_server_new_window (GdkBroadwayServer *server,
-                                int x,
-                                int y,
-                                int width,
-                                int height,
-                                gboolean is_temp)
-{
-  BroadwayRequestNewWindow msg;
-  guint32 serial, id;
-  BroadwayReply *reply;
-
-  msg.x = x;
-  msg.y = y;
-  msg.width = width;
-  msg.height = height;
-  msg.is_temp = is_temp;
-
-  serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_NEW_WINDOW);
-  reply = gdk_broadway_server_wait_for_reply (server, serial);
-
-  g_assert (reply->base.type == BROADWAY_REPLY_NEW_WINDOW);
-
-  id = reply->new_window.id;
-  
-  g_free (reply);
-
-  return id;
-}
-
-void
-_gdk_broadway_server_destroy_window (GdkBroadwayServer *server,
-                                    gint id)
-{
-  BroadwayRequestDestroyWindow msg;
-
-  msg.id = id;
-  gdk_broadway_server_send_message (server, msg,
-                                   BROADWAY_REQUEST_DESTROY_WINDOW);
-}
-
-gboolean
-_gdk_broadway_server_window_show (GdkBroadwayServer *server,
-                                 gint id)
-{
-  BroadwayRequestShowWindow msg;
-
-  msg.id = id;
-  gdk_broadway_server_send_message (server, msg,
-                                   BROADWAY_REQUEST_SHOW_WINDOW);
-  
-  return TRUE;
-}
-
-gboolean
-_gdk_broadway_server_window_hide (GdkBroadwayServer *server,
-                                 gint id)
-{
-  BroadwayRequestHideWindow msg;
-
-  msg.id = id;
-  gdk_broadway_server_send_message (server, msg,
-                                   BROADWAY_REQUEST_HIDE_WINDOW);
-  
-  return TRUE;
-}
-
-void
-_gdk_broadway_server_window_set_transient_for (GdkBroadwayServer *server,
-                                              gint id, gint parent)
-{
-  BroadwayRequestSetTransientFor msg;
-
-  msg.id = id;
-  msg.parent = parent;
-  gdk_broadway_server_send_message (server, msg,
-                                   BROADWAY_REQUEST_SET_TRANSIENT_FOR);
-}
-
-gboolean
-_gdk_broadway_server_window_translate (GdkBroadwayServer *server,
-                                      gint id,
-                                      cairo_region_t *area,
-                                      gint            dx,
-                                      gint            dy)
-{
-  BroadwayRequestTranslate *msg;
-  cairo_rectangle_int_t rect;
-  int i, n_rects;
-  gsize msg_size;
-
-  n_rects = cairo_region_num_rectangles (area);
-
-  msg_size = sizeof (BroadwayRequestTranslate) + (n_rects-1) * sizeof (BroadwayRect);
-  msg = g_malloc (msg_size);
-
-  msg->id = id;
-  msg->dx = dx;
-  msg->dy = dy;
-  msg->n_rects = n_rects;
-  
-  for (i = 0; i < n_rects; i++)
-    {
-      cairo_region_get_rectangle (area, i, &rect);
-      msg->rects[i].x = rect.x;
-      msg->rects[i].y = rect.y;
-      msg->rects[i].width = rect.width;
-      msg->rects[i].height = rect.height;
-    }
-
-  gdk_broadway_server_send_message_with_size (server, (BroadwayRequestBase *)msg, msg_size,
-                                             BROADWAY_REQUEST_TRANSLATE);
-  g_free (msg);
-  return TRUE;
-}
-
-static char
-make_valid_fs_char (char c)
-{
-  if (c == 0 || c == '/')
-    return c + 1;
-  return c;
-}
-
-/* name must have at least space for 34 bytes */
-static int
-create_random_shm (char *name)
-{
-  guint32 r;
-  int i, o, fd;
-
-  while (TRUE)
-    {
-      o = 0;
-      name[o++] = '/';
-      for (i = 0; i < 32/4; i++)
-       {
-         r = g_random_int ();
-         name[o++] = make_valid_fs_char ((r >> 0) & 0xff);
-         name[o++] = make_valid_fs_char ((r >> 8) & 0xff);
-         name[o++] = make_valid_fs_char ((r >> 16) & 0xff);
-         name[o++] = make_valid_fs_char ((r >> 24) & 0xff);
-       }
-      name[o++] = 0;
-  
-      fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
-      if (fd >= 0)
-       return fd;
-
-      if (errno != EEXIST)
-       {
-         g_printerr ("Unable to allocate shared mem for window");
-         exit (1);
-       }
-    }
-
-}
-
-static const cairo_user_data_key_t gdk_broadway_shm_cairo_key;
-
-typedef struct {
-  char name[34];
-  void *data;
-  gsize data_size;
-} BroadwayShmSurfaceData;
-
-static void
-shm_data_destroy (void *_data)
-{
-  BroadwayShmSurfaceData *data = _data;
-
-  munmap (data->data, data->data_size);
-  shm_unlink (data->name);
-  g_free (data);
-}
-
-cairo_surface_t *
-_gdk_broadway_server_create_surface (int                 width,
-                                    int                 height)
-{
-  BroadwayShmSurfaceData *data;
-  cairo_surface_t *surface;
-  int res;
-  int fd;
-
-  data = g_new (BroadwayShmSurfaceData, 1);
-  data->data_size = width * height * sizeof (guint32);
-  
-  fd = create_random_shm (data->name);
-
-  res = ftruncate (fd, data->data_size);
-  g_assert (res != -1);
-
-  data->data = mmap(0, data->data_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
-  (void) close(fd);
-
-  surface = cairo_image_surface_create_for_data ((guchar *)data->data,
-                                                CAIRO_FORMAT_RGB24, width, height, width * sizeof (guint32));
-  g_assert (surface != NULL);
-  
-  cairo_surface_set_user_data (surface, &gdk_broadway_shm_cairo_key,
-                              data, shm_data_destroy);
-
-  return surface;
-}
-
-void
-_gdk_broadway_server_window_update (GdkBroadwayServer *server,
-                                   gint id,
-                                   cairo_surface_t *surface)
-{
-  BroadwayRequestUpdate msg;
-  BroadwayShmSurfaceData *data;
-
-  data = cairo_surface_get_user_data (surface, &gdk_broadway_shm_cairo_key);
-  g_assert (data != NULL);
-
-  msg.id = id;
-  memcpy (msg.name, data->name, 34);
-  msg.width = cairo_image_surface_get_width (surface);
-  msg.height = cairo_image_surface_get_height (surface);
-  
-  gdk_broadway_server_send_message (server, msg, 
-                                   BROADWAY_REQUEST_UPDATE);
-}
-
-gboolean
-_gdk_broadway_server_window_move_resize (GdkBroadwayServer *server,
-                                        gint id,
-                                        int x,
-                                        int y,
-                                        int width,
-                                        int height)
-{
-  BroadwayRequestMoveResize msg;
-
-  msg.id = id;
-  msg.x = x;
-  msg.y = y;
-  msg.width = width;
-  msg.height = height;
-
-  gdk_broadway_server_send_message (server, msg,
-                                   BROADWAY_REQUEST_MOVE_RESIZE);
-
-  return TRUE;
-}
-
-GdkGrabStatus
-_gdk_broadway_server_grab_pointer (GdkBroadwayServer *server,
-                                  gint id,
-                                  gboolean owner_events,
-                                  guint32 event_mask,
-                                  guint32 time_)
-{
-  BroadwayRequestGrabPointer msg;
-  guint32 serial, status;
-  BroadwayReply *reply;
-
-  msg.id = id;
-  msg.owner_events = owner_events;
-  msg.event_mask = event_mask;
-  msg.time_ = time_;
-
-  serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_GRAB_POINTER);
-  reply = gdk_broadway_server_wait_for_reply (server, serial);
-
-  g_assert (reply->base.type == BROADWAY_REPLY_GRAB_POINTER);
-
-  status = reply->grab_pointer.status;
-  
-  g_free (reply);
-
-  return status;
-}
-
-guint32
-_gdk_broadway_server_ungrab_pointer (GdkBroadwayServer *server,
-                                    guint32    time_)
-{
-  BroadwayRequestUngrabPointer msg;
-  guint32 serial, status;
-  BroadwayReply *reply;
-
-  msg.time_ = time_;
-
-  serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_UNGRAB_POINTER);
-  reply = gdk_broadway_server_wait_for_reply (server, serial);
-
-  g_assert (reply->base.type == BROADWAY_REPLY_UNGRAB_POINTER);
-
-  status = reply->ungrab_pointer.status;
-  
-  g_free (reply);
-
-  return status;
-}
diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c
new file mode 100644 (file)
index 0000000..a2f9e00
--- /dev/null
@@ -0,0 +1,685 @@
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "gdkbroadway-server.h"
+
+#include "gdkprivate-broadway.h"
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gio/gunixsocketaddress.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+typedef struct BroadwayInput BroadwayInput;
+
+struct _GdkBroadwayServer {
+  GObject parent_instance;
+
+  guint32 next_serial;
+  GSocketConnection *connection;
+
+  guint32 recv_buffer_size;
+  guint8 recv_buffer[1024];
+
+  guint process_input_idle;
+  GList *incomming;
+  
+};
+
+struct _GdkBroadwayServerClass
+{
+  GObjectClass parent_class;
+};
+
+static gboolean input_available_cb (gpointer stream, gpointer user_data);
+
+G_DEFINE_TYPE (GdkBroadwayServer, gdk_broadway_server, G_TYPE_OBJECT)
+
+static void
+gdk_broadway_server_init (GdkBroadwayServer *server)
+{
+  server->next_serial = 1;
+}
+
+static void
+gdk_broadway_server_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_broadway_server_parent_class)->finalize (object);
+}
+
+static void
+gdk_broadway_server_class_init (GdkBroadwayServerClass * class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = gdk_broadway_server_finalize;
+}
+
+gboolean
+_gdk_broadway_server_lookahead_event (GdkBroadwayServer  *server,
+                                     const char         *types)
+{
+
+  return FALSE;
+}
+
+gulong
+_gdk_broadway_server_get_next_serial (GdkBroadwayServer *server)
+{
+  return (gulong)server->next_serial;
+}
+
+GdkBroadwayServer *
+_gdk_broadway_server_new (int port, GError **error)
+{
+  GdkBroadwayServer *server;
+  char *basename;
+  GSocketClient *client;
+  GSocketConnection *connection;
+  GSocketAddress *address;
+  GPollableInputStream *pollable;
+  GInputStream *in;
+  GSource *source;
+  char *path;
+
+  basename = g_strdup_printf ("broadway%d.socket", port);
+  path = g_build_filename (g_get_user_runtime_dir (), basename, NULL);
+  g_free (basename);
+
+  address = g_unix_socket_address_new_with_type (path, -1,
+                                                G_UNIX_SOCKET_ADDRESS_ABSTRACT);
+  g_free (path);
+
+  client = g_socket_client_new ();
+
+  error = NULL;
+  connection = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (address), NULL, error);
+  
+  g_object_unref (address);
+  g_object_unref (client);
+
+  if (connection == NULL)
+    return NULL;
+
+  server = g_object_new (GDK_TYPE_BROADWAY_SERVER, NULL);
+  server->connection = connection;
+
+  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
+  pollable = G_POLLABLE_INPUT_STREAM (in);
+
+  source = g_pollable_input_stream_create_source (pollable, NULL);
+  g_source_attach (source, NULL);
+  g_source_set_callback (source, (GSourceFunc)input_available_cb, server, NULL);
+
+  return server;
+}
+
+guint32
+_gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server)
+{
+  return 0;
+}
+
+static guint32
+gdk_broadway_server_send_message_with_size (GdkBroadwayServer *server, BroadwayRequestBase *base,
+                                           gsize size, guint32 type)
+{
+  GOutputStream *out;
+  gsize written;
+
+  base->size = size;
+  base->type = type;
+  base->serial = server->next_serial++;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection));
+
+  if (!g_output_stream_write_all (out, base, size, &written, NULL, NULL))
+    {
+      g_printerr ("Unable to write to server\n");
+      exit (1);
+    }
+
+  g_assert (written == size);
+
+  return base->serial;
+}
+
+#define gdk_broadway_server_send_message(_server, _msg, _type) \
+  gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type)
+
+static void
+parse_all_input (GdkBroadwayServer *server)
+{
+  guint8 *p, *end;
+  guint32 size;
+  BroadwayReply *reply;
+
+  p = server->recv_buffer;
+  end = p + server->recv_buffer_size;
+
+  while (p + sizeof (guint32) <= end)
+    {
+      memcpy (&size, p, sizeof (guint32));
+      if (p + size > end)
+       break;
+
+      reply = g_memdup (p, size);
+      p += size;
+
+      server->incomming = g_list_append (server->incomming, reply);
+    }
+  
+  if (p < end)
+    memmove (server->recv_buffer, p, end - p);
+  server->recv_buffer_size = end - p;
+}
+
+static void
+read_some_input_blocking (GdkBroadwayServer *server)
+{
+  GInputStream *in;
+  gssize res;
+
+  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
+
+  g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
+  res = g_input_stream_read (in, &server->recv_buffer[server->recv_buffer_size],
+                            sizeof (server->recv_buffer) - server->recv_buffer_size,
+                            NULL, NULL);
+
+  if (res <= 0)
+    {
+      g_printerr ("Unable to read from broadway server\n");
+      exit (1);
+    }
+
+  server->recv_buffer_size += res;
+}
+
+static void
+read_some_input_nonblocking (GdkBroadwayServer *server)
+{
+  GInputStream *in;
+  GPollableInputStream *pollable;
+  gssize res;
+  GError *error;
+
+  in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
+  pollable = G_POLLABLE_INPUT_STREAM (in);
+
+  g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
+  error = NULL;
+  res = g_pollable_input_stream_read_nonblocking (pollable, &server->recv_buffer[server->recv_buffer_size],
+                                                 sizeof (server->recv_buffer) - server->recv_buffer_size,
+                                                 NULL, &error);
+
+  if (res < 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+    {
+      g_error_free (error);
+      res = 0;
+    }
+  else if (res <= 0)
+    {
+      g_printerr ("Unable to read from broadway server: %s\n", error ? error->message : "eof");
+      exit (1);
+    }
+
+  server->recv_buffer_size += res;
+}
+
+static BroadwayReply *
+find_response_by_serial (GdkBroadwayServer *server, guint32 serial)
+{
+  GList *l;
+
+  for (l = server->incomming; l != NULL; l = l->next)
+    {
+      BroadwayReply *reply = l->data;
+
+      if (reply->base.in_reply_to == serial)
+       return reply;
+    }
+
+  return NULL;
+}
+
+static void
+process_input_messages (GdkBroadwayServer *server)
+{
+  BroadwayReply *reply;
+
+  if (server->process_input_idle != 0)
+    {
+      g_source_remove (server->process_input_idle);
+      server->process_input_idle = 0;
+    }
+  
+  while (server->incomming)
+    {
+      reply = server->incomming->data;
+      server->incomming =
+       g_list_delete_link (server->incomming,
+                           server->incomming);
+
+      if (reply->base.type == BROADWAY_REPLY_EVENT)
+       _gdk_broadway_events_got_input (&reply->event.msg);
+      else
+       g_warning ("Unhandled reply type %d\n", reply->base.type);
+      g_free (reply);
+    }
+}
+
+static gboolean
+process_input_idle_cb (GdkBroadwayServer *server)
+{
+  server->process_input_idle = 0;
+  process_input_messages (server);
+  return G_SOURCE_REMOVE;
+}
+
+static void
+queue_process_input_at_idle (GdkBroadwayServer *server)
+{
+  if (server->process_input_idle == 0)
+    server->process_input_idle =
+      g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc)process_input_idle_cb, server, NULL);
+}
+
+static gboolean
+input_available_cb (gpointer stream, gpointer user_data)
+{
+  GdkBroadwayServer *server = user_data;
+
+  read_some_input_nonblocking (server);
+  parse_all_input (server);
+
+  process_input_messages (server);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static BroadwayReply *
+gdk_broadway_server_wait_for_reply (GdkBroadwayServer *server,
+                                   guint32 serial)
+{ 
+  BroadwayReply *reply;
+  
+  while (TRUE)
+    {
+      reply = find_response_by_serial (server, serial);
+      if (reply)
+       {
+         server->incomming = g_list_remove (server->incomming, reply);
+         return reply;
+       }
+
+      read_some_input_blocking (server);
+      parse_all_input (server);
+    }
+
+  queue_process_input_at_idle (server);
+}
+
+void
+_gdk_broadway_server_flush (GdkBroadwayServer *server)
+{
+  BroadwayRequestFlush msg;
+
+  gdk_broadway_server_send_message(server, msg, BROADWAY_REQUEST_FLUSH);
+}
+
+void
+_gdk_broadway_server_sync (GdkBroadwayServer *server)
+{
+  BroadwayRequestSync msg;
+  guint32 serial;
+  BroadwayReply *reply;
+
+  serial = gdk_broadway_server_send_message (server, msg,
+                                            BROADWAY_REQUEST_SYNC);
+  reply = gdk_broadway_server_wait_for_reply (server, serial);
+
+  g_assert (reply->base.type == BROADWAY_REPLY_SYNC);
+
+  g_free (reply);
+
+  return;
+}
+
+void
+_gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
+                                 guint32            *toplevel,
+                                 gint32             *root_x,
+                                 gint32             *root_y,
+                                 guint32            *mask)
+{
+  BroadwayRequestQueryMouse msg;
+  guint32 serial;
+  BroadwayReply *reply;
+
+  serial = gdk_broadway_server_send_message (server, msg,
+                                            BROADWAY_REQUEST_QUERY_MOUSE);
+  reply = gdk_broadway_server_wait_for_reply (server, serial);
+
+  g_assert (reply->base.type == BROADWAY_REPLY_QUERY_MOUSE);
+
+  if (toplevel)
+    *toplevel = reply->query_mouse.toplevel;
+  if (root_x)
+    *root_x = reply->query_mouse.root_x;
+  if (root_y)
+    *root_y = reply->query_mouse.root_y;
+  if (mask)
+    *mask = reply->query_mouse.mask;
+  
+  g_free (reply);
+}
+
+guint32
+_gdk_broadway_server_new_window (GdkBroadwayServer *server,
+                                int x,
+                                int y,
+                                int width,
+                                int height,
+                                gboolean is_temp)
+{
+  BroadwayRequestNewWindow msg;
+  guint32 serial, id;
+  BroadwayReply *reply;
+
+  msg.x = x;
+  msg.y = y;
+  msg.width = width;
+  msg.height = height;
+  msg.is_temp = is_temp;
+
+  serial = gdk_broadway_server_send_message (server, msg,
+                                            BROADWAY_REQUEST_NEW_WINDOW);
+  reply = gdk_broadway_server_wait_for_reply (server, serial);
+
+  g_assert (reply->base.type == BROADWAY_REPLY_NEW_WINDOW);
+
+  id = reply->new_window.id;
+  
+  g_free (reply);
+
+  return id;
+}
+
+void
+_gdk_broadway_server_destroy_window (GdkBroadwayServer *server,
+                                    gint id)
+{
+  BroadwayRequestDestroyWindow msg;
+
+  msg.id = id;
+  gdk_broadway_server_send_message (server, msg,
+                                   BROADWAY_REQUEST_DESTROY_WINDOW);
+}
+
+gboolean
+_gdk_broadway_server_window_show (GdkBroadwayServer *server,
+                                 gint id)
+{
+  BroadwayRequestShowWindow msg;
+
+  msg.id = id;
+  gdk_broadway_server_send_message (server, msg,
+                                   BROADWAY_REQUEST_SHOW_WINDOW);
+  
+  return TRUE;
+}
+
+gboolean
+_gdk_broadway_server_window_hide (GdkBroadwayServer *server,
+                                 gint id)
+{
+  BroadwayRequestHideWindow msg;
+
+  msg.id = id;
+  gdk_broadway_server_send_message (server, msg,
+                                   BROADWAY_REQUEST_HIDE_WINDOW);
+  
+  return TRUE;
+}
+
+void
+_gdk_broadway_server_window_set_transient_for (GdkBroadwayServer *server,
+                                              gint id, gint parent)
+{
+  BroadwayRequestSetTransientFor msg;
+
+  msg.id = id;
+  msg.parent = parent;
+  gdk_broadway_server_send_message (server, msg,
+                                   BROADWAY_REQUEST_SET_TRANSIENT_FOR);
+}
+
+gboolean
+_gdk_broadway_server_window_translate (GdkBroadwayServer *server,
+                                      gint id,
+                                      cairo_region_t *area,
+                                      gint            dx,
+                                      gint            dy)
+{
+  BroadwayRequestTranslate *msg;
+  cairo_rectangle_int_t rect;
+  int i, n_rects;
+  gsize msg_size;
+
+  n_rects = cairo_region_num_rectangles (area);
+
+  msg_size = sizeof (BroadwayRequestTranslate) + (n_rects-1) * sizeof (BroadwayRect);
+  msg = g_malloc (msg_size);
+
+  msg->id = id;
+  msg->dx = dx;
+  msg->dy = dy;
+  msg->n_rects = n_rects;
+  
+  for (i = 0; i < n_rects; i++)
+    {
+      cairo_region_get_rectangle (area, i, &rect);
+      msg->rects[i].x = rect.x;
+      msg->rects[i].y = rect.y;
+      msg->rects[i].width = rect.width;
+      msg->rects[i].height = rect.height;
+    }
+
+  gdk_broadway_server_send_message_with_size (server, (BroadwayRequestBase *)msg, msg_size,
+                                             BROADWAY_REQUEST_TRANSLATE);
+  g_free (msg);
+  return TRUE;
+}
+
+static char
+make_valid_fs_char (char c)
+{
+  if (c == 0 || c == '/')
+    return c + 1;
+  return c;
+}
+
+/* name must have at least space for 34 bytes */
+static int
+create_random_shm (char *name)
+{
+  guint32 r;
+  int i, o, fd;
+
+  while (TRUE)
+    {
+      o = 0;
+      name[o++] = '/';
+      for (i = 0; i < 32/4; i++)
+       {
+         r = g_random_int ();
+         name[o++] = make_valid_fs_char ((r >> 0) & 0xff);
+         name[o++] = make_valid_fs_char ((r >> 8) & 0xff);
+         name[o++] = make_valid_fs_char ((r >> 16) & 0xff);
+         name[o++] = make_valid_fs_char ((r >> 24) & 0xff);
+       }
+      name[o++] = 0;
+  
+      fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+      if (fd >= 0)
+       return fd;
+
+      if (errno != EEXIST)
+       {
+         g_printerr ("Unable to allocate shared mem for window");
+         exit (1);
+       }
+    }
+
+}
+
+static const cairo_user_data_key_t gdk_broadway_shm_cairo_key;
+
+typedef struct {
+  char name[34];
+  void *data;
+  gsize data_size;
+} BroadwayShmSurfaceData;
+
+static void
+shm_data_destroy (void *_data)
+{
+  BroadwayShmSurfaceData *data = _data;
+
+  munmap (data->data, data->data_size);
+  shm_unlink (data->name);
+  g_free (data);
+}
+
+cairo_surface_t *
+_gdk_broadway_server_create_surface (int                 width,
+                                    int                 height)
+{
+  BroadwayShmSurfaceData *data;
+  cairo_surface_t *surface;
+  int res;
+  int fd;
+
+  data = g_new (BroadwayShmSurfaceData, 1);
+  data->data_size = width * height * sizeof (guint32);
+  
+  fd = create_random_shm (data->name);
+
+  res = ftruncate (fd, data->data_size);
+  g_assert (res != -1);
+
+  data->data = mmap(0, data->data_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
+  (void) close(fd);
+
+  surface = cairo_image_surface_create_for_data ((guchar *)data->data,
+                                                CAIRO_FORMAT_RGB24, width, height, width * sizeof (guint32));
+  g_assert (surface != NULL);
+  
+  cairo_surface_set_user_data (surface, &gdk_broadway_shm_cairo_key,
+                              data, shm_data_destroy);
+
+  return surface;
+}
+
+void
+_gdk_broadway_server_window_update (GdkBroadwayServer *server,
+                                   gint id,
+                                   cairo_surface_t *surface)
+{
+  BroadwayRequestUpdate msg;
+  BroadwayShmSurfaceData *data;
+
+  data = cairo_surface_get_user_data (surface, &gdk_broadway_shm_cairo_key);
+  g_assert (data != NULL);
+
+  msg.id = id;
+  memcpy (msg.name, data->name, 34);
+  msg.width = cairo_image_surface_get_width (surface);
+  msg.height = cairo_image_surface_get_height (surface);
+  
+  gdk_broadway_server_send_message (server, msg, 
+                                   BROADWAY_REQUEST_UPDATE);
+}
+
+gboolean
+_gdk_broadway_server_window_move_resize (GdkBroadwayServer *server,
+                                        gint id,
+                                        int x,
+                                        int y,
+                                        int width,
+                                        int height)
+{
+  BroadwayRequestMoveResize msg;
+
+  msg.id = id;
+  msg.x = x;
+  msg.y = y;
+  msg.width = width;
+  msg.height = height;
+
+  gdk_broadway_server_send_message (server, msg,
+                                   BROADWAY_REQUEST_MOVE_RESIZE);
+
+  return TRUE;
+}
+
+GdkGrabStatus
+_gdk_broadway_server_grab_pointer (GdkBroadwayServer *server,
+                                  gint id,
+                                  gboolean owner_events,
+                                  guint32 event_mask,
+                                  guint32 time_)
+{
+  BroadwayRequestGrabPointer msg;
+  guint32 serial, status;
+  BroadwayReply *reply;
+
+  msg.id = id;
+  msg.owner_events = owner_events;
+  msg.event_mask = event_mask;
+  msg.time_ = time_;
+
+  serial = gdk_broadway_server_send_message (server, msg,
+                                            BROADWAY_REQUEST_GRAB_POINTER);
+  reply = gdk_broadway_server_wait_for_reply (server, serial);
+
+  g_assert (reply->base.type == BROADWAY_REPLY_GRAB_POINTER);
+
+  status = reply->grab_pointer.status;
+  
+  g_free (reply);
+
+  return status;
+}
+
+guint32
+_gdk_broadway_server_ungrab_pointer (GdkBroadwayServer *server,
+                                    guint32    time_)
+{
+  BroadwayRequestUngrabPointer msg;
+  guint32 serial, status;
+  BroadwayReply *reply;
+
+  msg.time_ = time_;
+
+  serial = gdk_broadway_server_send_message (server, msg,
+                                            BROADWAY_REQUEST_UNGRAB_POINTER);
+  reply = gdk_broadway_server_wait_for_reply (server, serial);
+
+  g_assert (reply->base.type == BROADWAY_REPLY_UNGRAB_POINTER);
+
+  status = reply->ungrab_pointer.status;
+  
+  g_free (reply);
+
+  return status;
+}